#include <iostream>
#include <string>
#include <cstring> // For strlen
#include <cstdio>

using namespace std;

class Test{
    public:
        int data;
        char *ptr;

        Test(){
            data = 0;
            ptr = new char[10];// Allocate memory for ptr size 10 bytes
        }

        Test(int data,const char *src){
            this->data = data;
            if(src){
                this->ptr = new char[strlen(src)+1];
                strcpy(this->ptr, src);
            }
        }

        Test(const Test &t){// Copy constructor, 当用一个构造好的对象来初始化另一个对象时调用
            cout << "Copy constructor called" << endl;
            this->data = t.data;
            if(strlen(t.ptr)){
                this->ptr = new char[strlen(t.ptr)+1];
                strcpy(this->ptr,t.ptr);
            }else{
                ptr = new char[10];
            }
        }

        ~Test(){
            if(ptr){
                delete[] ptr;
            }
        }

        //该运算符重载函数由 左操作数调用，右操作数作为实参传递给函数，
        //触发： t1+t3 -> t1.operator + (t3)
        Test operator + (const Test &t){
            cout << "Test operator + (Test &t)" << endl;
            Test tmp;
            tmp.data = this->data + t.data;
            tmp.ptr = new char[strlen(this->ptr)+strlen(t.ptr)+1];
            memset(tmp.ptr,0, strlen(this->ptr)+strlen(t.ptr)+1);

            strcat(tmp.ptr,this->ptr);
            strcat(tmp.ptr,t.ptr);

            return tmp;
        }

        bool operator > (const Test &t){
            cout << "Test operator > (Test &t)" << endl;
            if(strcmp(this->ptr, t.ptr)>0){
                return true;
            }
            return false;
        }

        char operator [] (int index){//index是下标
            cout << "char operator [] (int index)" << endl;
            if(index < 0 || index >= strlen(this->ptr)){
                return '\0';
            }

            return this->ptr[index];
        }

        Test &operator = (const Test &t){
            cout << "Test &operator = (const Test &t)" << endl;
            delete[] this->ptr;
            this->ptr = new char[strlen(t.ptr)+1];
            strcpy(this->ptr,t.ptr);

            this->data = t.data;
            return *this;
        }

        Test &operator ++(){//前置++ t3=++t1
            cout << "Test &operator ++()" << endl;
            ++data;
            return *this;
        }

        Test operator ++ (int){//后置++ t3=t1++
            cout << "Test opertor ++(int)" << endl;
            Test tmp = *this;
            data++;

            return tmp;
        }

        friend ostream &operator << (ostream &os, const Test &t)// cout << t1 : 左操作数不是一个Test对象
        //将左操作数和右操作数当作实参进行传递  cout是ostream这个类的一个实例化对象
        {
            os << t.data << endl;
            os << t.ptr << endl;

            return os;
        }
            
};

Test func(){//这里的返回值不能是引用，引用是一个存在的变量的别名，而这个函数不能返回一个在函数栈上的对象的引用
    Test t;//局部变量，随着函数调用结束会被销毁，也就是在函数栈上
    return t;
}

Test &func(Test &t){
    return t;//这里能够返回引用是因为函数栈是main函数而不是这个函数
}

int main(){
    //=================================+运算符重载======================================
    // Test t1(10,"hello world");

    // Test t2 = t1;
    // cout <<t2.data<<" "<<t2.ptr<<endl;

    // Test t3 (10,"fuc*");
    // Test t4 = t1 + t3;//20, "hello worldfuc*"
    // /*
    // *执行以上语句Test t4 = t1 + t3会调用哪些函数
    // *Test operator + (Test &t)
    // *因为这句执行到最后实际是Test t4 = tmp；所以还会调用拷贝构造函数(而且在operator函数内部也会调用一次）
    // */
    // cout << t4.data <<" " << t4.ptr << endl;

    //======================================>运算符重载====================================
    // Test t1(10,"hello");
    // Test t2(20,"heLlo");
    // if(t1>t2){
    //     cout << "t1 > t2" << endl;
    // }else
    // {
    //     cout << "t1 <= t2" << endl;
    // }

    //=====================================[]重载==========================================
    // Test t1(10,"hello world");
    // cout << t1[3] << endl;

    //==============================================="="重载=======================================
    // Test t1(10,"hello");
    // Test t2(10,"hello1");
    // t1=t2;
    // cout << t1.ptr << endl;
    // printf("%p,%p\n",t1.ptr,t2.ptr);

    //===============================================++重载==========================================
    // Test t1(10,"hello");
    // Test t2;
    // Test t3;

    // t2 = ++t1;
    // cout << t1.data << endl;
    // cout << t2.data << endl;

    // t3 = t2++;
    // cout << t2.data << endl;
    // cout << t3.data << endl;

    //==============================================<<重载===========================================
    // Test t1(10, "hello");
    // cout << t1;
    
    return 0;
}